package cn.openea.perpartner.payment.web.coupon.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.openea.perpartner.common.core.text.Convert;
import cn.openea.perpartner.common.core.web.domain.AjaxResult;
import cn.openea.perpartner.payment.rabbit.domain.BusinessDto;
import cn.openea.perpartner.payment.rabbit.factory.BusinessServiceFactory;
import cn.openea.perpartner.payment.rabbit.service.BusinessService;
import cn.openea.perpartner.payment.rabbit.service.impl.PublisherService;
import cn.openea.perpartner.payment.web.coupon.entity.Coupon;
import cn.openea.perpartner.payment.web.coupon.entity.CouponBatch;
import cn.openea.perpartner.payment.web.coupon.entity.dto.CouponDto;
import cn.openea.perpartner.payment.web.coupon.enums.CouponStatus;
import cn.openea.perpartner.payment.web.coupon.mapper.CouponBatchMapper;
import cn.openea.perpartner.payment.web.coupon.mapper.CouponMapper;
import cn.openea.perpartner.payment.web.coupon.service.ICouponService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.TimerTask;

/**
 * 用户优惠券表(CouponUser)表服务实现类
 *
 * @author Weird077
 * @since 2023-04-14 14:29:50
 */
@Service("couponService")
public class CouponServiceImpl extends MPJBaseServiceImpl<CouponMapper, Coupon> implements ICouponService, BusinessService {
    @Autowired
    private PublisherService publisherService;
    @Autowired
    private CouponBatchMapper couponBatchMapper;

    @Override
    public boolean issueCoupon(Coupon coupon) {
        LambdaQueryWrapper<CouponBatch> wrapper = Wrappers.<CouponBatch>lambdaQuery()
                .eq(CouponBatch::getCouponId, coupon.getCouponId());
        CouponBatch couponBatch = couponBatchMapper.selectOne(wrapper);
        int aging = couponBatch.getAging();
        coupon.setBatchId(couponBatch.getBatchId());
        boolean isSuccess = save(coupon);
        DateTime now = DateUtil.date();
        DateTime nextTime = DateUtil.offsetDay(now, aging);
        long delayTime = DateUtil.betweenMs(now, nextTime);
        BusinessDto business = BusinessDto.builder()
                .beanName("couponService")
                .delayTime(delayTime)
                .params(BeanUtil.toBean(coupon, JSONObject.class))
                .build();
        publisherService.execute(business);
        return isSuccess;
    }

    @Override
    public List<CouponDto> selectUserCouponList(CouponDto coupon) {
        MPJLambdaWrapper<Coupon> wrapper = new MPJLambdaWrapper<Coupon>()
                .selectAll(Coupon.class)
                .select(CouponBatch::getCouponName, CouponBatch::getCouponAmount)
                .select(CouponBatch::getUseThresholds, CouponBatch::getAging)
                .select(CouponBatch::getUseScope, CouponBatch::getCouponType)
                .leftJoin(CouponBatch.class, CouponBatch::getCouponId, Coupon::getCouponId)
                .eq(Coupon::getUserId, coupon.getUserId());
        if (StrUtil.isBlank(coupon.getStatus())) {
            wrapper.eq(Coupon::getStatus, "0");
        } else {
            wrapper.eq(Coupon::getStatus, coupon.getStatus());
        }
        if (StrUtil.isNotBlank(coupon.getCouponName())) {
            wrapper.like(CouponBatch::getCouponName, coupon.getCouponName());
        }
        if (StrUtil.isNotBlank(coupon.getCouponType())) {
            wrapper.eq(CouponBatch::getCouponType, coupon.getCouponType());
        }
        if (StrUtil.isNotBlank(coupon.getUseScope())) {
            List<String> scopeList = new ArrayList<>();
            scopeList.add("ALL");
            scopeList.add(coupon.getUseScope());
            wrapper.in(CouponBatch::getUseScope, scopeList);
        }
        wrapper.orderByDesc(CouponBatch::getCouponAmount);
        return baseMapper.selectJoinList(CouponDto.class, wrapper);
    }

    @Override
    public AjaxResult getCouponCount(Coupon coupon) {
        List<Coupon> couponList = list(Wrappers.<Coupon>lambdaQuery()
                .eq(Coupon::getUserId, coupon.getUserId()));
        AjaxResult ajaxResult = AjaxResult.success();
        for (CouponStatus value : CouponStatus.values()) {
            String status = Convert.toStr(value.ordinal());
            ajaxResult.put(status, couponList.stream().filter(coup -> coup.getStatus().equals(status)).count());
        }
        return ajaxResult;
    }

    @Override
    public TimerTask execute(BusinessDto business) {
        return new TimerTask() {
            @Override
            public void run() {
                Coupon coupon = BeanUtil.toBean(business.getParams(), Coupon.class);
                update(Wrappers.<Coupon>lambdaUpdate()
                        .set(Coupon::getStatus, "2")
                        .eq(Coupon::getStatus, "0")
                        .eq(Coupon::getId, coupon.getId())
                        .eq(Coupon::getUserId, coupon.getUserId())
                        .eq(Coupon::getCouponId, coupon.getCouponId()));
            }
        };
    }

    @Override
    public void afterPropertiesSet() {
        BusinessServiceFactory.register("couponService", this);
    }
    @Override
    @Scheduled(cron = "0 0 2 * * ?")
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public void updateCouponStatus() {
        update(Wrappers.<Coupon>lambdaUpdate()
                .set(Coupon::getStatus, "2")
                .eq(Coupon::getStatus, "0")
                .lt(Coupon::getValidateTime, DateUtil.date()));
    }
}

